home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 3 / Gold Medal Software - Volume 3 (Gold Medal) (1994).iso / print / cramv33.arj / CRAM.C < prev    next >
Text File  |  1993-08-02  |  28KB  |  723 lines

  1. /*
  2.  *   ------------------------------------
  3.  *   C R A M   -   the ASCII file reducer
  4.  *   ------------------------------------
  5.  *
  6.  *   CRAM  -  ASCII File Reducer  - V3.3
  7.  *   Copyright (c) 1988-93  -  Dean Tutterow  -  All Rights Reserved
  8.  *   
  9.  *   What  does  it do?   It crams as  much text  as possible onto a page
  10.  *   in  reduced format.   Using  subscript characters as  the font on an
  11.  *   Epson printer,  you  can print up to 79 characters wide and 154 rows
  12.  *   long in 2 columns.   That  works  out to  5-6 pages of  text on each
  13.  *   printed  page.   In  normal use  with  files with embedded formfeeds
  14.  *   respected, you get 4 pages of text on each printed page.
  15.  *
  16.  *   CRAM also supports the HPLJ  and related printers.  Prior to release
  17.  *   V2.2, the file CRAM.DAT  would have to be  used to send the required
  18.  *   initialization and termination strings.  Version 2.2 has implemented
  19.  *   embedded HPLJ strings.  The current  functionality is to select font
  20.  *   number  1006  (6  point  font)  and  compute  the  appropriate  line
  21.  *   separation.  At  termination, font  number 1012  (12 point  font) is
  22.  *   selected and the line  separation is set to  6 lines per inch.  This
  23.  *   implementation is only an example of  what YOU can do.  I personally
  24.  *   do not use the  standard LJ fonts.  I  load three soft fonts, 1006 -
  25.  *   the 6 pt. font,  1012 - a 12  pt. default font, and  1024 - a 24 pt.
  26.  *   font.   If  you have  a  LJ  printer, change  the  initialization of
  27.  *   GLOBAL  symbol HPLJ  from 0 to  1.   Add in  YOUR initialization and
  28.  *   termination  strings  and  recompile!
  29.  *
  30.  *   CRAM  was  written  after  I  had  printed  another  of  those  LONG
  31.  *   documentation files.  I was tired of those STACKS of listings, etc.,
  32.  *   that  gathered  dust  simply  because they  were too much trouble to
  33.  *   handle  once I printed  them.   Now  the  printed listings are small
  34.  *   enough to keep in notebooks.   As a bonus, CRAM is especially useful
  35.  *   for printing program listings.  The reduced format is just the thing
  36.  *   to show program structure and the BIG picture!
  37.  *
  38.  *   While not limited to Epson printers,  it is hardcoded for my FX-86e.
  39.  *   Of course you can provide your own setup and un-setup codes for your
  40.  *   printer, and include them in a printer setup file for CRAM to use.
  41.  *
  42.  *   USAGE:
  43.  *   
  44.  *   CRAM srcfile crammedfile [/options]
  45.  *
  46.  *   where [/options] are:
  47.  *          /COLUMN=n       with 1 ≤ n ≤ 10
  48.  *          /DUAL           automatically format dual-sided pages
  49.  *          /EPSON          default printer
  50.  *          /EVEN           prints EVEN pages only
  51.  *          /FF             if <FF> encountered, align to next logical page
  52.  *          /HPLJ           select HPLJ printer
  53.  *          /LARGE          use PICA format to get 137 chars/line, EPSON only
  54.  *          /NONE           use to have CRAM function as a column program only
  55.  *          /ODD            prints ODD pages only
  56.  *          /PAGELENGTH=n   may vary printed page length from 1-154 lines
  57.  *          /SKIP=n         number of columns to ignore in srcfile
  58.  *          /TAB=n          number of columns representing a tab
  59.  *          /TEST           test the options on the srcfile, no output files
  60.  *          /WHITE=n        number of characters of whitespace on gutter of page
  61.  *          /WIDTH=n        width of CRAM's page, normally 160
  62.  *   
  63.  *   The  srcfile  should  be  a  valid DOS filename;  wildcards  are not
  64.  *   accepted.   You  need  only  supply  enough  to the  option  name to
  65.  *   distinguish it from the other options, for example /C=1 and /N.
  66.  *   
  67.  *   As a daily VAX user,  I  have tried to implement the straightforward
  68.  *   command-line interface that VMS affords the user.  While the srcfile
  69.  *   and crammedfile must be in that order,  the options may be spread at
  70.  *   will along the command line.
  71.  *
  72.  *   The options are much easier understood after a few practice sessions.
  73.  *   '/COLUMN=n' is  used whenever you want more or less than the standard
  74.  *   two columns on each page.   While  normally  defaulted  to two-column
  75.  *   operation, only the first 79 characters on each line (unless some are
  76.  *   /SKIP-ped) are  visible.   '/FF' respects  embedded  formfeeds in the
  77.  *   text.   Normally off, this option moves to the next logical page when
  78.  *   encountered.   The pagelength is adjustable  through  '/PAGELENGTH=n'
  79.  *   The default is 154 rows,  which allows two pages in each column since
  80.  *   most formatters place 66 lines per page.  If you want your one-column
  81.  *   printing shifted right on the page so that you have whitespace on the
  82.  *   gutter  of the page,  then '/WHITE'  is  just  the ticket.   Finally,
  83.  *   '/SKIP=n' ignores the first 'n' characters on each input line.   This
  84.  *   allows you to print 79 useful characters in each column when printing
  85.  *   formatted files  with spaces or tabs in the first 'n' columns.   It's
  86.  *   your job to try the rest.
  87.  */
  88.  
  89. #include <stdio.h>
  90. #include <stdlib.h>
  91. #include <string.h>
  92.  
  93. /*  G L O B A L   D E F I N E S  */
  94. #define byte         unsigned char
  95. #define MAX_CHAR     160
  96. #define MAX_ROWS     154
  97. #define MAX_ELEMENTS 10
  98. #define PICA         137
  99. #define ELITE        160
  100. enum    OE           { ALL,  ODD,   EVEN };
  101. enum    PR           { NONE, EPSON, HPLJ };
  102.  
  103. /*  E R R O R   C O D E S  */
  104. #define FILENAME_TROUBLE    0x101
  105. #define INVALID_OPTION      0x102
  106. #define MISSING_FILE        0x103
  107. #define INVLD_NUM_COLUMNS   0x104
  108. #define INVLD_TAB_LENGTH    0x105
  109. #define NO_DISK_SPACE       0x106
  110.  
  111. /*  S E V E R I T Y   C O D E S  */
  112. #define FATAL         "F"
  113. #define SEVERE        "S"
  114. #define WARNING       "W"
  115. #define INFORMATIONAL "I"
  116.  
  117. /*  G L O B A L   D A T A  */ 
  118. char    BUFFER[MAX_ROWS][MAX_CHAR+1];
  119. char    PRINTER_INIT[200];
  120. char    PRINTER_TERM[200];
  121. char    SOURCE[120];
  122. int     SKIP_PT     = 0;
  123. int     NUM_COLS    = 2;
  124. int     NUM_CHAR    = MAX_CHAR;
  125. int     NUM_ROWS    = MAX_ROWS;
  126. int     WHITE       = 0;
  127. int     TAB         = 8;
  128. int     DISPLAYABLE;
  129. byte    NUM_FILES   = 0;
  130. byte    FF          = 0;
  131. byte    DUAL        = 0;
  132. byte    LEFT_EDGE;
  133. byte    TEST        = 0;
  134. int     PAGE_COUNT  = 0;
  135. int     LINE_WIDTH  = 0;
  136. long    LINE_COUNT  = 0;
  137. int     FF_FOUND    = 0;
  138. enum    OE ODD_EVEN = ALL;
  139. enum    PR FORMAT   = EPSON;
  140. char    *INFILE = 0, *OUTFILE = 0;
  141. FILE    *INPUT,  *OUT_ODD, *OUT_EVN;
  142.  
  143. void    _nullcheck();
  144. void    _setenvp();
  145. void    open_files();
  146. void    format_page();
  147. void    print_copyright();
  148. void    filter_input();
  149. void    get_printer_defaults();
  150. void    parse_command_line();
  151. void    get_filenames_and_options();
  152. void    err_exit();
  153.  
  154. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  155.  
  156. int     main( argc, argv )
  157.  
  158. int     argc;
  159. char    *argv[];
  160. {
  161.         int     i, value;
  162.         char    equivalence[100], parsed[120], *elements[MAX_ELEMENTS];
  163.         char    *option, *parse_option(), *status;
  164.  
  165.         /* Tell them who I am. */
  166.         print_copyright();
  167.  
  168.         /* Parse the command line for files and switches. */
  169.         memset( equivalence, '\0', sizeof( equivalence ) );
  170.         memset( parsed, '\0', sizeof( parsed ) );
  171.         memset( SOURCE, '\0', sizeof( SOURCE ) );
  172.         strcpy( SOURCE, argv[0] );
  173.         i = '\\';
  174.         if ( ( status = strrchr( SOURCE, i ) ) == 0 )
  175.             SOURCE[0] = 0;
  176.         else
  177.             *(status+1)= 0;
  178.         for ( i = 1; i < argc; i++ ){
  179.             strcat( equivalence, argv[i] );
  180.             strcat( equivalence, " " );
  181.         };
  182.         value = MAX_ELEMENTS;
  183.         parse_command_line( equivalence, parsed, elements, &value );
  184.         get_filenames_and_options( elements, &value, &INFILE, &OUTFILE );
  185.         get_printer_defaults();
  186.  
  187.         /* Open the proper files for reading/writing. */
  188.         open_files();
  189.  
  190.         /* Send the printer setup string. */
  191.         if ( ! TEST ) {
  192.             fputs( PRINTER_INIT, OUT_ODD );
  193.             fputs( PRINTER_INIT, OUT_EVN );
  194.         };
  195.  
  196.         /* Read from the input file and build the output file in memory. */
  197.         format_page();
  198.  
  199.         /* Send the printer termination string and close all files. */
  200.         if ( ! TEST ) {
  201.             fputs( PRINTER_TERM, OUT_ODD );
  202.             fputs( PRINTER_TERM, OUT_EVN );
  203.             fflush( OUT_ODD );
  204.             fflush( OUT_EVN );
  205.             fclose( OUT_ODD );
  206.             fclose( OUT_EVN );
  207.         };
  208.         fclose( INPUT );
  209.         return( 0 );
  210. }
  211.  
  212. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  213.  
  214. void    open_files()
  215. {
  216.         int     i;
  217.         char    *name, autoname[100] = "\0";
  218.  
  219.         /* We always have an input file to open. */
  220.         INPUT = fopen( INFILE,  "rt" );
  221.  
  222.         /* Flag any pesky filename errors. */
  223.         if ( !INPUT )
  224.             err_exit( FILENAME_TROUBLE, FATAL );
  225.  
  226.         /* If we are just testing, 'return to sender'. */
  227.         if ( TEST ) return;
  228.  
  229.         /* Figure out the proper output file(s) to open. */
  230.         if ( DUAL || ODD_EVEN != ALL ) NUM_FILES = 1;
  231.         switch ( NUM_FILES ) {
  232.             case 2 :
  233.                 OUT_ODD = OUT_EVN = fopen( OUTFILE, "wt" );
  234.                 break;
  235.             case 1 :
  236.                 if ( OUTFILE ) strcpy( autoname, OUTFILE );
  237.                 strcat( autoname, INFILE );
  238.                 i = '.';
  239.                 name = strchr( autoname, i );
  240.                 if ( ! name ) name = autoname + strlen( autoname );
  241.                 if ( DUAL ) {
  242.                     strcpy( name, ".ODD" );
  243.                     OUT_ODD = fopen( autoname, "wt" );
  244.                     strcpy( name, ".EVN" );
  245.                     OUT_EVN = fopen( autoname, "wt" );
  246.                     }
  247.                 else {
  248.                     strcpy( name, ".CRM" );
  249.                     OUT_ODD = OUT_EVN = fopen( autoname, "wt" );
  250.                 };
  251.                 break;
  252.         };
  253.  
  254.         /* Flag any pesky filename errors. */
  255.         if ( !OUT_ODD || !OUT_EVN )
  256.             err_exit( FILENAME_TROUBLE, FATAL );
  257. }
  258.  
  259. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  260.  
  261. void    format_page()
  262. {
  263.         int     i, j, x, carryover, value, lr, current_col, status;
  264.         long    position, lc, tlc;
  265.         char    *file_status, line[MAX_CHAR+20];
  266.         FILE    *output;
  267.  
  268.         carryover = lc = tlc = 0;
  269.         do {
  270.             PAGE_COUNT++;
  271.             LEFT_EDGE = ( !(PAGE_COUNT & 1) && ( DUAL || (ODD_EVEN == EVEN) ) ) ? 0 : WHITE;
  272.             memset( BUFFER, ' ', NUM_ROWS * (MAX_CHAR+1) );
  273.             for ( i=0; i < NUM_ROWS; i++ ) BUFFER[i][NUM_CHAR] = 0;
  274.             for ( current_col=1, lr=0; current_col<=NUM_COLS; current_col++ ) {
  275.               if ( carryover ) {
  276.                 filter_input( &line[0] );
  277.                 x = strlen( line );
  278.                 if ( x > LINE_WIDTH ) LINE_WIDTH = x;
  279.                 line[DISPLAYABLE] = '\0';
  280.                 lc++;
  281.                 if ( current_col != NUM_COLS )
  282.                     strncpy( &BUFFER[0][LEFT_EDGE], &line[0], strlen( line ) );
  283.                 else
  284.                     strcpy( &BUFFER[0][LEFT_EDGE], &line[0] );
  285.               };
  286.               for ( i=carryover; i < NUM_ROWS; i++ ) {
  287.                 carryover = 0;
  288.                 position = ftell( INPUT );
  289.                 file_status = fgets( line, 159, INPUT );
  290.                 if ( file_status == NULL ) break;
  291.                 if ( strstr( &line[1], "\f" ) ) {
  292.                   for ( j = 1; line[j] != '\f'; j++ ) {};
  293.                   fseek( INPUT, (position+j), SEEK_SET );
  294.                   line[j] = '\0';
  295.                 };
  296.                 if ( line[0] == '\f' ) {
  297.                     FF_FOUND++;
  298.                     if ( lc > LINE_COUNT ) LINE_COUNT = lc;
  299.                     tlc += lc;
  300.                     lc   = 0;
  301.                     if ( FF ) {
  302.                       if ( i <= (NUM_ROWS+1)/2 )
  303.                         i = carryover = (NUM_ROWS+1)/2;
  304.                       else  {
  305.                         carryover = 1; break;
  306.                       };
  307.                     };
  308.                 };
  309.                 filter_input( &line[0] );
  310.                 x = strlen( line );
  311.                 if ( x > LINE_WIDTH ) LINE_WIDTH = x;
  312.                 line[DISPLAYABLE] = '\0';
  313.                 lc++;
  314.                 if ( current_col != NUM_COLS )
  315.                     strncpy( &BUFFER[i][LEFT_EDGE], &line[0], strlen( line ) );
  316.                 else
  317.                     strcpy( &BUFFER[i][LEFT_EDGE], &line[0] );
  318.               };
  319.               if ( i > lr ) lr = i;
  320.               if ( file_status == NULL ) break;
  321.               LEFT_EDGE = LEFT_EDGE + DISPLAYABLE + 1;
  322.               if ( carryover > 1 ) carryover = 0;
  323.             };
  324.  
  325.             /* Write out a page buffer and get ready for next page. */
  326.             if ( TEST ) {
  327.                 if ( lc > LINE_COUNT ) LINE_COUNT = lc;
  328.                 continue;
  329.             };
  330.             if ( ( ODD_EVEN == ALL  ) ||
  331.                ( ( ODD_EVEN == ODD  ) &&  ( PAGE_COUNT & 1 ) ) ||
  332.                ( ( ODD_EVEN == EVEN ) && !( PAGE_COUNT & 1 ) ) ) {
  333.               output = ( PAGE_COUNT & 1 ) ? OUT_ODD : OUT_EVN;
  334.               for ( i=0; i < lr; i++ ) {
  335.                 j = strlen( &BUFFER[i][0] );
  336.                 if ( j )
  337.                   if ( BUFFER[i][j-1] == '\n' ) j--;
  338.                 if ( j > (NUM_CHAR-1) )  j = NUM_CHAR - 1;
  339.                 BUFFER[i][j]   = '\n';
  340.                 BUFFER[i][j+1] = '\0';
  341.                 status = fputs( &BUFFER[i][0], output );
  342.               };
  343.               if ( status == EOF ) err_exit( NO_DISK_SPACE, SEVERE );
  344.               if ( file_status != NULL ) fputs( "\xc\0", output );
  345.             };
  346.         } while ( file_status );
  347.  
  348.         if ( TEST ) {
  349.             tlc += lc;
  350.             fprintf( stderr, "\tForm Feeds ... %d\n", FF_FOUND );
  351.             fprintf( stderr, "\tPage Count ... %d\n", PAGE_COUNT );
  352.             fprintf( stderr, "\tLine Count ... %ld (maximum input page length is %ld)\n", tlc, LINE_COUNT );
  353.             fprintf( stderr, "\tLine Width ... %d (maximum %d displayable)\n", LINE_WIDTH, DISPLAYABLE );
  354.         };
  355.         return;
  356. }
  357.  
  358. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  359.  
  360. void    _nullcheck () {};
  361. void    _setenvp () {};
  362.  
  363.  
  364. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  365.  
  366. void    print_copyright()
  367. {
  368.         fprintf( stderr, "CRAM  -  ASCII File Reducer  -  V3.3\n" );
  369.         fprintf( stderr, "Copyright (c) 1988-93  -  Dean Tutterow  -  All Rights Reserved\n" );
  370. }
  371.  
  372. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  373.  
  374. void    filter_input( line )
  375.  
  376. char    *line;
  377. {
  378.     int     i, n;
  379.         char    newline[MAX_CHAR+20], *oldline;
  380.  
  381.     /* Clean all tabs and formfeeds from the input line. */
  382.     oldline = line;
  383.         memset( newline, '\0', sizeof( newline ) );
  384.         for ( i = 0; i <= MAX_CHAR+1; ) {
  385.           if ( *line == '\0' ) { newline[i] = '\0'; break; }
  386.           if ( *line == '\f' ) { line++; continue; }
  387.           if ( *line == '\n' ) *line = ' ';
  388.           if ( *line == '\t' ) {
  389.         n = i;
  390.             while ( n >= 0 )
  391.               n -= TAB;
  392.         n = -n;
  393.             strncpy( &newline[i], "        ", n );
  394.             i += ( n - 1 ); }
  395.           else
  396.             newline[i] = *line;
  397.       i++;
  398.           line++;
  399.         };
  400.         if ( newline[0] != 0x0D )
  401.           strcpy( oldline, &newline[SKIP_PT] );
  402.     else
  403.           strcpy( oldline, &newline[0] );
  404. }
  405.  
  406. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  407.  
  408. void    get_printer_defaults()
  409. {
  410.         char    *file_status, filename[120];
  411.         float   x;
  412.  
  413.         if ( FORMAT == NONE ) return;
  414.         strcpy( filename, SOURCE );
  415.         strcat( filename, "CRAM.DAT" );
  416.         INPUT = fopen( filename, "rt" );
  417.         if ( !INPUT ) {
  418.           switch ( FORMAT ) {
  419.  
  420.             case EPSON:
  421.                  if ( NUM_CHAR == PICA )
  422.                      strcpy( PRINTER_INIT, "\x1b\x33\xf\x1b\x53\x30\xf\0" );
  423.                  else
  424.                      strcpy( PRINTER_INIT, "\x1b\x33\xf\x1b\x53\x30\x1b\x4d\xf\0" );
  425.                  strcpy( PRINTER_TERM, "\x1b\x32\x1b\x54\x1b\x50\x12\x1a\0" );
  426.                  break;
  427.  
  428.             case HPLJ:
  429.                  /* Compute vertical scale factor for line spacing. */
  430.                  x = 48.0 / ( (NUM_ROWS+2) / 10.0 );
  431.                  sprintf( PRINTER_INIT, "\x1b(1006X\x1b&l%2.3fC", x );
  432.                  sprintf( PRINTER_TERM, "\x1b(1012X\x1b&l6D" );
  433.                  break;
  434.           };
  435.           return;
  436.         }
  437.         file_status = fgets( PRINTER_INIT, sizeof( PRINTER_INIT ), INPUT );
  438.         if ( file_status == NULL ) goto file_error;
  439.         file_status = fgets( PRINTER_TERM, sizeof( PRINTER_TERM ), INPUT );
  440.         if ( file_status == NULL ) goto file_error;
  441.         file_error:
  442.         fclose( INPUT );
  443.         return;
  444. }
  445.  
  446.  
  447. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  448.  
  449. char    *parse_option( option, output )
  450.  
  451. char    *option, **output;
  452. {
  453.         int offset;
  454.  
  455.         if ( *option != '/' ) return( 0 );
  456.         if ( !( offset = strcspn( option, "=:" ) ) ) return( 0 );
  457.         if ( offset == strlen( option ) ) return( 0 );
  458.         *output = option + offset + 1;
  459.         return( (char *)output );
  460. }
  461.  
  462. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  463.  
  464. void    parse_command_line( input, output, arrayed, number )
  465.  
  466. char    *input, *output, *arrayed[];
  467. int    *number;
  468. {
  469.     int     i, j, k, paren;
  470.         char    temp[100], *env;
  471.  
  472.         /* Get any parameters which may be in the CRAM environment variable. */
  473.         temp[0] = (int) env = 0;
  474.         env = getenv( "CRAM" );
  475.         if ( env ) {
  476.             strcpy( temp, env );
  477.             strcat( temp, " " );
  478.         };
  479.         strcat( temp, input );
  480.  
  481.         /* Convert input line to upper case */
  482.         for ( i=0; i < strlen( temp ); i++ )
  483.           (temp)[i] = toupper( (temp)[i] );
  484.  
  485.         (output)[0] = ' ';
  486.  
  487.         for ( i=k=paren=0, j=1;( i < strlen( temp ) && k <= *number ); i++ ) {
  488.           switch ( (temp)[i] ) {
  489.             case ','  : if ( paren ) { (output)[j] = (temp)[i]; break; }
  490.             case ' '  :
  491.             case '\t' : if ( (output)[j-1]!=' ' ) (output)[j]   = ' '; break;
  492.             case '/'  : if ( (output)[j-1]!=' ' ) (output)[j++] = ' '; paren--;
  493.             case '('  : paren += 2;
  494.             case ')'  : paren--;
  495.             default   : (output)[j] = (temp)[i];
  496.       }
  497.       j++;
  498.  
  499.           /*
  500.           ** If this is the start of an argument, then place its address
  501.           ** in the argument list & null-terminate the previous argument.
  502.           */
  503.           if ( (output)[j-1] != ' ' && (output)[j-2] == ' ' ) {
  504.             if ( k != *number ) {
  505.               (arrayed)[k] = &(output)[j-1];
  506.           k++; 
  507.             };
  508.             (output)[j-2] = '\0';
  509.           };
  510.         };
  511.         (output)[j] = '\0';
  512.     *number = k;
  513. };
  514.  
  515. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  516.  
  517. void    get_filenames_and_options( elements, value, INFILE, OUTFILE )
  518.  
  519. char    **INFILE, **OUTFILE, *elements[];
  520. int    *value;
  521. {
  522.     int    first, i;
  523.         char    *status, *option, *parse_option(), first_char;
  524.  
  525.         for ( i = 0, first = 1; i < *value; i++ ) {
  526.           if ( *elements[i] != '/' ) {
  527.             if ( first ) { *INFILE = elements[i]; first = 0; }
  528.         else *OUTFILE = elements[i];
  529.         NUM_FILES++; }
  530.       else {
  531.             first_char = *(elements[i] + 1);
  532.             switch ( first_char ) {
  533.  
  534.                 case 'C' :      /* # OF COLUMNS PARAMETER */
  535.                         status = parse_option( elements[i], &option );
  536.                         if ( status ) sscanf( option, "%d", &NUM_COLS );
  537.                         else NUM_COLS = 2;
  538.                         if ( NUM_COLS > 10  || NUM_COLS < 1 )
  539.                             err_exit( INVLD_NUM_COLUMNS, FATAL );
  540.             break;
  541.  
  542.                 case 'D' :      /* DUAL - PRINT ODD/EVEN PAGES */
  543.                         DUAL = 1;
  544.                         ODD_EVEN = ALL;
  545.                         break;
  546.  
  547.                 case 'E' :
  548.                         first_char = *(elements[i] + 2);
  549.                         switch ( first_char ) {
  550.                             case 'P':   /* EPSON PRINTER */
  551.                                   FORMAT = EPSON;
  552.                                   break;
  553.  
  554.                             case 'V':   /* PRINT EVEN PAGES ONLY */
  555.                                   if ( ! DUAL ) ODD_EVEN = EVEN;
  556.                                   break;
  557.                         };
  558.                         break;
  559.  
  560.                 case 'F' :      /* RECOGNIZE FORMFEEDS */
  561.             FF = 1;
  562.             break;
  563.  
  564.                 case 'H' :      /* HPLJ PRINTER */
  565.                         FORMAT   = HPLJ;
  566.                         NUM_CHAR = MAX_CHAR;
  567.                         break;
  568.  
  569.                 case 'L' :      /* LARGE-SMALL PRINT( CHARS/LINE = 137 )*/
  570.                         if ( FORMAT == EPSON ) NUM_CHAR = PICA;
  571.                         break;
  572.  
  573.                 case 'N' :      /* NO PRINTER FORMATTING */
  574.                         FORMAT = NONE;
  575.             break;
  576.  
  577.                 case 'O' :      /* PRINT ODD PAGES ONLY */
  578.                         if ( ! DUAL ) ODD_EVEN = ODD;
  579.             break;
  580.  
  581.                 case 'P' :      /* LINES-PER-PAGE PARAMETER */
  582.                         status = parse_option( elements[i], &option );
  583.                         if ( status ) sscanf( option, "%d", &NUM_ROWS );
  584.             else NUM_ROWS = MAX_ROWS;
  585.                         if ( NUM_ROWS > MAX_ROWS ) NUM_ROWS = MAX_ROWS;
  586.                         break;
  587.  
  588.         case 'S' :    /* START INPUT PROCESSING AT THIS POSITON */
  589.                         status = parse_option( elements[i], &option );
  590.                         if ( status ) sscanf( option, "%d", &SKIP_PT );
  591.             else SKIP_PT = 0;
  592.             break;
  593.  
  594.                 case 'T' :
  595.                         first_char = *(elements[i] + 2);
  596.                         switch ( first_char ) {
  597.                             case 'A':   /* TAB INCREMENT */
  598.                                 status = parse_option( elements[i], &option );
  599.                                 if ( status ) sscanf( option, "%d", &TAB );
  600.                                 else TAB = 8;
  601.                                 if ( TAB > 8 || TAB < 1 ) {
  602.                                     err_exit( INVLD_TAB_LENGTH, WARNING );
  603.                                     TAB = 8;
  604.                                 };
  605.                                 break;
  606.  
  607.                             case 'E' :  /* TEST SOURCE FILE */
  608.                                 TEST = 1;
  609.                                 break;
  610.                         };
  611.                         break;
  612.  
  613.                 case 'W' :      
  614.                         first_char = *(elements[i] + 2);
  615.                         switch ( first_char ) {
  616.                             case 'H':   /* WHITE SPACE ON GUTTER */
  617.                                 status = parse_option( elements[i], &option );
  618.                                 if ( status ) sscanf( option, "%d", &WHITE );
  619.                                 else WHITE = 35;
  620.                                 if ( WHITE > MAX_CHAR/2 ) WHITE = 35;
  621.                                 break;
  622.  
  623.                             case 'I':   /* WIDTH OF PAGE */
  624.                                 status = parse_option( elements[i], &option );
  625.                                 if ( status ) sscanf( option, "%d", &NUM_CHAR );
  626.                                 else NUM_CHAR = MAX_CHAR;
  627.                                 if ( NUM_CHAR > MAX_CHAR ) NUM_CHAR = MAX_CHAR;
  628.                                 break;
  629.                         };
  630.                         break;
  631.  
  632.                 default : 
  633.                         err_exit( INVALID_OPTION, WARNING );
  634.             };
  635.           };
  636.         };
  637.  
  638.         /* Compute the maximum displayable portion of the input line. */
  639.         DISPLAYABLE = ( NUM_CHAR - NUM_COLS + 1 - WHITE ) / NUM_COLS;
  640. }
  641.  
  642. /* /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\ */
  643.  
  644. void    err_exit( code, severity )
  645.  
  646. int    code;
  647. char    *severity;
  648. {
  649.     char     err_code[20], msg[50];
  650.  
  651.     /* Display an error message, delete output file, exit. */
  652.         switch ( code ) {
  653.  
  654.       case FILENAME_TROUBLE :
  655.                strcpy( msg, "Trouble opening files, please check filenames." );
  656.                strcpy( err_code, "FILEOPEN" );
  657.                break;
  658.  
  659.       case MISSING_FILE :
  660.                strcpy( msg, "You must specify an input and output file." );
  661.                strcpy( err_code, "MISSFILE" );
  662.                break;
  663.  
  664.       case INVALID_OPTION :
  665.                strcpy( msg, "You have specified an invalid option." );
  666.                strcpy( err_code, "INVLDOPT" );
  667.                break;
  668.  
  669.           case INVLD_NUM_COLUMNS :
  670.                strcpy( msg, "You have specified an invalid number of columns." );
  671.                strcpy( err_code, "IVLDCOLS" );
  672.                break;
  673.  
  674.           case INVLD_TAB_LENGTH :
  675.                strcpy( msg, "Tab length must be between 1 and 8 characters." );
  676.                strcpy( err_code, "IVLDTAB" );
  677.                break;
  678.  
  679.           case NO_DISK_SPACE :
  680.                strcpy( msg, "Not enough disk space for output file(s)." );
  681.                strcpy( err_code, "NODSKSPC" );
  682.                break;
  683.  
  684.           default : 
  685.                strcpy( msg, "Unknown error!" );
  686.                strcpy( err_code, "UNKNOWN" );
  687.         };
  688.  
  689.         fprintf( stderr, "\nCRAM-%c-%s, %s\n", *severity, err_code, msg );
  690.  
  691.         if ( *severity == 'F' ) {
  692.           fprintf( stderr, "\n  usage: CRAM infile outfile [options]\n\n" );
  693.           fprintf( stderr, "  where [options] and defaults are:\n" );
  694.           fprintf( stderr, "\t[/column=N]      2, 1 <= N <= 10\n" );
  695.           fprintf( stderr, "\t[/dual]          off, on automatically formats dual-sided pages\n" );
  696.           fprintf( stderr, "\t[/epson]         EPSON, default printer\n" );
  697.           fprintf( stderr, "\t[/even]          off, on prints even pages only\n" );
  698.           fprintf( stderr, "\t[/ff]            off, on recognizes form feeds\n" );
  699.           fprintf( stderr, "\t[/hplj]          off, on selects HPLJ printer\n" );
  700.           fprintf( stderr, "\t[/large]         off, on selects large EPSON print\n" );
  701.           fprintf( stderr, "\t[/none]          off, on selects no printer formatting\n" );
  702.           fprintf( stderr, "\t[/odd]           off, on prints odd pages only\n" );
  703.           fprintf( stderr, "\t[/pagelength=N]  154, 1 <= pagelength <= 154\n" );
  704.           fprintf( stderr, "\t[/skip=N]        0, # of chars to skip on each input line\n" );
  705.           fprintf( stderr, "\t[/tab=N]         8, # of chars representing a tab\n" );
  706.           fprintf( stderr, "\t[/test]          test the options on the srcfile\n" );
  707.           fprintf( stderr, "\t[/white=N]       0, # of chars of white space for gutter\n" );
  708.         };
  709.  
  710.         /* Close streams and delete partial output for TERMINAL failures. */
  711.         if ( ( *severity == 'F' ) || ( *severity == 'S' ) ) {
  712.           fflush( OUT_ODD );
  713.           fflush( OUT_EVN );
  714.           fclose( INPUT   );
  715.           fclose( OUT_ODD );
  716.           fclose( OUT_EVN );
  717.           unlink( OUTFILE );
  718.     
  719.       /* Exit with errorlevel 1 */
  720.           exit( 1 );
  721.         };
  722. }
  723.